package com.feng.openFeignPlus.register;

import com.feng.openFeignPlus.scan.Scanner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Component
public class RequestMappingRegister implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private RequestMappingHandlerMapping handlerMapping;


    private RequestMappingInfo.BuilderConfiguration config = new RequestMappingInfo.BuilderConfiguration();

    List<HandlerDefinition> handlerDefinitionList;

    private Set<String> uriSet = new HashSet<>();





    @Override
    public void onApplicationEvent(ContextRefreshedEvent event)   {
        this.config.setTrailingSlashMatch(handlerMapping.useTrailingSlashMatch());
        this.config.setContentNegotiationManager(handlerMapping.getContentNegotiationManager());

        if (handlerMapping.getPatternParser() != null) {
            this.config.setPatternParser(handlerMapping.getPatternParser());
            Assert.isTrue(!handlerMapping.useSuffixPatternMatch() && !handlerMapping.useRegisteredSuffixPatternMatch(),
                    "Suffix pattern matching not supported with PathPatternParser.");
        } else {
            this.config.setSuffixPatternMatch(handlerMapping.useSuffixPatternMatch());
            this.config.setRegisteredSuffixPatternMatch(handlerMapping.useRegisteredSuffixPatternMatch());
            this.config.setPathMatcher(handlerMapping.getPathMatcher());
        }
        this.packageScan();
        this.register();
    }

    void packageScan() {
        this.handlerDefinitionList = Scanner.handlerDefinitionList;
    }


    void register() {
        //扫描指定包路径
        //找到所有加了@Factory注解的类
        //找到类中用了Method的方法（封装一下）
        //注册到requestMapping
        handlerDefinitionList.forEach(each -> {
            try {
                register(each);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        });
    }

    void register(HandlerDefinition definition) throws NoSuchMethodException {
            if (uriSet.contains(definition.getPath())) return;
            //构造mapping
            RequestMappingInfo mappingInfo = RequestMappingInfo.paths(definition.getPath())
                    .params(definition.getParamsNameList().toArray(new String[]{}))
                    .methods(RequestMethod.POST)
                    .options(this.config)
                    .build();
            //注册mapping
            handlerMapping.registerMapping(mappingInfo,
                    definition.getHandlerName(),
                    definition.getFactoryClass().getDeclaredMethod(definition.getMethod().getName(), definition.getParamsTypeList().toArray(new Class[]{}))
            );
            uriSet.add(definition.getPath());
        System.out.println("register：" + definition.getPath());

    }

}
